﻿/**
* 一个用户
* @typedef {Object} T_USER
* @property {String} Platform - 玩家进入的平台
* @property {Number} ID
* @property {String} RegisterTime
* @property {String} Token
* @property {String} Account
* @property {String} Password
* @property {Number} Phone
* @property {String} Name
* @property {String} LastLoginTime
* @property {String} LastRefreshLoginTime
*/
/**
* 后台管理账号
* @typedef {Object} T_CENTER_USER
* @property {Number} ID
* @property {String} RegisterTime
* @property {String} Token
* @property {String} Account
* @property {String} Password
* @property {Number} Phone
* @property {String} Name
* @property {String} LastLoginTime
* @property {String} LastRefreshLoginTime
*/
/**
* 微信JSSDK wx.config 时必要的参数
* @typedef {Object} WXJSSDK
* @property {Boolean} debug
* @property {String} appId
* @property {Number} timestamp
* @property {String} nonceStr
* @property {String} signature
* @property {String} url
*/
/**
* @typedef {('1' | '2' | '5')} TestEnum - 测试枚举
* 多行注释
* aaa
* bbb
*/
export const TestEnum =
{
    /** 测试枚举字段 */
    a: 1,
    b: 2,
    c: 5,
}
/** 不需要登录的通用服务接口 */
const is =
{
    install: (vue) => vue.config.globalProperties.is = is,
    /** 后端接口的URL */
    url:  '',
    /** 状态码对应错误信息，错误码和错误信息的对象会回调给event.onerror事件 */
    error: { 0: '请求已中止' },
    /**
    * @typedef RequestEvent
    * @type {Object}
    * @property {function(XMLHttpRequest)} onopen - 请求准备发送时的事件
    * @property {function(XMLHttpRequest)} onloading - 请求正在加载的事件(readyState = 3)
    * @property {function(XMLHttpRequest)} oncomplete - 请求完成时的事件(readyState = 4)
    * @property {function(XMLHttpRequest)} onsuccess - 请求成功的事件(readyState = 4 && status == 200 && !response.errCode)
    * @property {function({ errCode: number, errMsg: string })} onerror - 请求发生错误时的事件(readyState = 4 && (status != 200 || response.errCode))
    * @property {function(ProgressEvent)} onprogress - 上传文件请求的进度事件
    */
    /** 接口请求的全局事件
    * @type {RequestEvent} */
    __event: undefined,
    /** 接口请求的全局事件
    * @type {RequestEvent} */
    event: undefined,
    /** 本次接口请求的临时事件，onprogress以外的全局事件任然会触发，临时事件优先于全局事件触发
    * @param {RequestEvent} event */
    eventonce(event)
    {
        this.__event = Object.assign({}, this.__event, event);
        return this;
    },
    /** 发送接口
    * @param {String} url - 接口url
    * @param {XMLHttpRequestBodyInit} [data] - 数据，可以是FormData或a=1&b=2格式的字符串
    * @param {('POST' | 'GET')} method - 默认POST
    */
    send(url, data, method = 'POST')
    {
        return new Promise((resolve, reject) =>
        {
            const req = new XMLHttpRequest();
            const event = this.__event;
            this.__event = undefined;
            req.onreadystatechange = async () =>
            {
                if (req.readyState == 4)
                {
                    event?.oncomplete?.(req) | this.event?.oncomplete?.(req);
                    if (req.status == 200)
                    {
                        let obj = null;
                        switch (req.responseType)
                        {
                            case 'text': if (req.response) obj = JSON.parse(req.responseText); break;
                            case 'blob':
                            if (req.response.type == 'text/plain') await req.response.text().then((value) => obj = JSON.parse(value));
                            else obj = req.response;
                            break;
                        }
                        if (obj && obj.errCode)
                        event?.onerror?.(obj) | this.event?.onerror?.(obj) | reject(obj);
                        else
                        event?.onsuccess?.(obj) | this.event?.onsuccess?.(obj) | resolve(obj);
                    }
                    else
                    {
                        let error = { errCode: req.status, errMsg: '' };
                        error.errMsg = this.error[req.status] || req.statusText;
                        event?.onerror?.(error) | this.event?.onerror?.(error) | reject(error);
                    }
                }
                else if (req.readyState == 3) event?.onloading?.(req) | this.event?.onloading?.(req);
            }
            req.open(method, this.url + url, true);
            req.upload.onprogress = event?.onprogress || this.event?.onprogress;
            req.responseType = 'text';
            if (event?.onopen) event.onopen(req);
            else req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
            this.event?.onopen?.(req);
            req.send(data);
        });
    },
    /** 调用下载文件的接口前调用
    * @param {string} filename - 下载文件的名字，例如download.csv
    * @example
    * api.download('download.csv').downloadCSV()
    */
    download(filename)
    {
        return this.eventonce(
        {
            oncomplete(req)
            {
                const a = window.document.createElement('a');
                a.href = URL.createObjectURL(req.response);
                a.download = filename;
                a.click();
            }
        })
    },
    /**
    * 发送短信验证码
    * @param {String} phone - 手机号码
    * @returns {Promise<Number>} - 再次发送冷却时间（秒）
    */
    SendSMSCode(phone)
    {
        const data = [];
        if (phone) data.push("phone=" + encodeURIComponent(phone));
        return this.send("1/SendSMSCode", data.join('&'));
    },
    /**
    * @typedef LoginBySMSCode
    * @property {String} phone - 手机号
    * @property {String} code - 验证码
    */
    /**
    * 手机验证码登录，没有账号则注册账号
    * @param {String | LoginBySMSCode} phone - 手机号
    * @example
    * {
    *   phone: undefined,
    *   code: undefined,
    * }
    * @param {String} code - 验证码
    * @returns {Promise<T_USER>} - 返回账号信息
    */
    LoginBySMSCode(phone, code)
    {
        arguments.length == 1 && ({ phone, code } = arguments[0])
        const data = [];
        if (phone) data.push("phone=" + encodeURIComponent(phone));
        if (code) data.push("code=" + encodeURIComponent(code));
        return this.send("1/LoginBySMSCode", data.join('&'));
    },
    /**
    * Token登录
    * @param {String} token
    * @returns {Promise<any>}
    */
    LoginByToken(token)
    {
        const data = [];
        if (token) data.push("token=" + encodeURIComponent(token));
        return this.send("1/LoginByToken", data.join('&'));
    },
    /**
    * @typedef LoginByPassword
    * @property {String} phone
    * @property {String} password
    */
    /**
    * 密码登录
    * @param {String | LoginByPassword} phone
    * @example
    * {
    *   phone: undefined,
    *   password: undefined,
    * }
    * @param {String} password
    * @returns {Promise<T_USER>}
    */
    LoginByPassword(phone, password)
    {
        arguments.length == 1 && ({ phone, password } = arguments[0])
        const data = [];
        if (phone) data.push("phone=" + encodeURIComponent(phone));
        if (password) data.push("password=" + encodeURIComponent(password));
        return this.send("1/LoginByPassword", data.join('&'));
    },
    /**
    * @typedef ForgetPassword
    * @property {String} phone
    * @property {String} code
    * @property {String} password
    */
    /**
    * 忘记密码：手机号和验证码登录，并修改密码
    * @param {String | ForgetPassword} phone
    * @example
    * {
    *   phone: undefined,
    *   code: undefined,
    *   password: undefined,
    * }
    * @param {String} code
    * @param {String} password
    * @returns {Promise<T_USER>}
    */
    ForgetPassword(phone, code, password)
    {
        arguments.length == 1 && ({ phone, code, password } = arguments[0])
        const data = [];
        if (phone) data.push("phone=" + encodeURIComponent(phone));
        if (code) data.push("code=" + encodeURIComponent(code));
        if (password) data.push("password=" + encodeURIComponent(password));
        return this.send("1/ForgetPassword", data.join('&'));
    },
    /**
    * 微信登录
    * @param {String} code
    * @returns {Promise<any>}
    */
    LoginByWX(code)
    {
        const data = [];
        if (code) data.push("code=" + encodeURIComponent(code));
        return this.send("1/LoginByWX", data.join('&'));
    },
    /**
    * 清理用户缓存，数据库有修改时，可以用此接口强制清空用户缓存而同步数据库数据
    * @param {Number} id
    * @returns {Promise<any>}
    */
    ClearUserCache(id)
    {
        const data = [];
        if (id) data.push("id=" + id);
        return this.send("1/ClearUserCache", data.join('&'));
    },
    /**
    * @typedef CenterLoginByPassword
    * @property {String} name
    * @property {String} password
    */
    /**
    * @param {String | CenterLoginByPassword} name
    * @example
    * {
    *   name: undefined,
    *   password: undefined,
    * }
    * @param {String} password
    * @returns {Promise<T_CENTER_USER>}
    */
    CenterLoginByPassword(name, password)
    {
        arguments.length == 1 && ({ name, password } = arguments[0])
        const data = [];
        if (name) data.push("name=" + encodeURIComponent(name));
        if (password) data.push("password=" + encodeURIComponent(password));
        return this.send("1/CenterLoginByPassword", data.join('&'));
    },
    /**
    * @typedef CenterLoginBySMSCode
    * @property {String} phone
    * @property {String} code
    */
    /**
    * @param {String | CenterLoginBySMSCode} phone
    * @example
    * {
    *   phone: undefined,
    *   code: undefined,
    * }
    * @param {String} code
    * @returns {Promise<T_CENTER_USER>}
    */
    CenterLoginBySMSCode(phone, code)
    {
        arguments.length == 1 && ({ phone, code } = arguments[0])
        const data = [];
        if (phone) data.push("phone=" + encodeURIComponent(phone));
        if (code) data.push("code=" + encodeURIComponent(code));
        return this.send("1/CenterLoginBySMSCode", data.join('&'));
    },
    /**
    * @param {File} file
    * @returns {Promise<any>}
    */
    UploadImage(file)
    {
        const data = new FormData();
        if (file) data.append("file", file);
        return this.send("1/UploadImage", data);
    },
    /**
    * @param {File} file
    * @returns {Promise<any>}
    */
    UploadFile(file)
    {
        const data = new FormData();
        if (file) data.append("file", file);
        return this.send("1/UploadFile", data);
    },
    /**
    * 微信支付回调
    * @returns {Promise<any>}
    */
    WeChatPayCallback()
    {
        return this.send("1/WeChatPayCallback");
    },
    /**
    * 微信支付退款回调
    * @returns {Promise<any>}
    */
    WeChatRefundCallback()
    {
        return this.send("1/WeChatRefundCallback");
    },
    /**
    * 微信JSSDK wx.config 时必要的参数
    * @param {String} url
    * @returns {Promise<any>}
    */
    WXJSSDK(url)
    {
        const data = [];
        if (url) data.push("url=" + encodeURIComponent(url));
        return this.send("1/WXJSSDK", data.join('&'));
    },
    /**
    * @typedef AlipayCallback
    * @property {String} trade_no
    * @property {String} out_trade_no
    * @property {String} buyer_id
    * @property {String} buyer_logon_id
    * @property {String} trade_status
    * @property {String} total_amount
    * @property {String} gmt_payment
    */
    /**
    * 支付宝支付回调
    * @param {String | AlipayCallback} trade_no
    * @example
    * {
    *   trade_no: undefined,
    *   out_trade_no: undefined,
    *   buyer_id: undefined,
    *   buyer_logon_id: undefined,
    *   trade_status: undefined,
    *   total_amount: undefined,
    *   gmt_payment: undefined,
    * }
    * @param {String} out_trade_no
    * @param {String} buyer_id
    * @param {String} buyer_logon_id
    * @param {String} trade_status
    * @param {String} total_amount
    * @param {String} gmt_payment
    * @returns {Promise<String>}
    */
    AlipayCallback(trade_no, out_trade_no, buyer_id, buyer_logon_id, trade_status, total_amount, gmt_payment)
    {
        arguments.length == 1 && ({ trade_no, out_trade_no, buyer_id, buyer_logon_id, trade_status, total_amount, gmt_payment } = arguments[0])
        const data = [];
        if (trade_no) data.push("trade_no=" + encodeURIComponent(trade_no));
        if (out_trade_no) data.push("out_trade_no=" + encodeURIComponent(out_trade_no));
        if (buyer_id) data.push("buyer_id=" + encodeURIComponent(buyer_id));
        if (buyer_logon_id) data.push("buyer_logon_id=" + encodeURIComponent(buyer_logon_id));
        if (trade_status) data.push("trade_status=" + encodeURIComponent(trade_status));
        if (total_amount) data.push("total_amount=" + encodeURIComponent(total_amount));
        if (gmt_payment) data.push("gmt_payment=" + encodeURIComponent(gmt_payment));
        return this.send("1/AlipayCallback", data.join('&'));
    },
    /**
    * @returns {Promise<any>}
    */
    Test()
    {
        return this.send("1/Test");
    },
    /**
    * @returns {Promise<T_USER[]>}
    */
    GetUsers()
    {
        return this.send("1/GetUsers");
    },
};
export default is
